package com.prognos.service.harvester.impl;

import com.google.common.collect.Lists;
import com.prognos.domain.info.InfoSource;
import com.prognos.domain.info.SourceDirectory;
import com.prognos.domain.selector.CssSelector;
import com.prognos.domain.selector.Selector;
import com.prognos.service.InfoSourceService;
import com.prognos.service.SourceDirectoryService;
import com.prognos.service.harvester.HarvesterService;
import com.prognos.service.harvester.KeywordExtractor;
import org.apache.log4j.Logger;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.List;

@Service("HarvesterService")
public class HarvesterServiceImpl implements HarvesterService {

    private final SourceDirectoryService sourceDirectoryService;
    private final InfoSourceService infoSourceService;
    private static final Logger logger = Logger.getLogger(HarvesterServiceImpl.class);
    private final KeywordExtractor keywordExtractor;

    @Autowired
    public HarvesterServiceImpl(SourceDirectoryService sourceDirectoryService,
                                InfoSourceService infoSourceService, KeywordExtractor keywordExtractor) {
        this.sourceDirectoryService = sourceDirectoryService;
        this.infoSourceService = infoSourceService;
        this.keywordExtractor = keywordExtractor;
    }

    @Override
    @Transactional
    public void startHarvest() {
        try {
            List<SourceDirectory> availableSourceDictionary = sourceDirectoryService.getDirectoriesToHarvest();
            logger.debug("tamaño - " + availableSourceDictionary.size());
            for (SourceDirectory sourceDirectory : availableSourceDictionary) {
                List<String> sourceUrls = processInfoSource(sourceDirectory);
                for (String url : sourceUrls) {
                    String sourceUrl = "";
                    if (!sourceDirectory.getFullUrl()) {
                        sourceUrl += sourceDirectory.getUrl();
                    }
                    sourceUrl += url;
                    if (!infoSourceService.urlExists(sourceUrl)) {
                        addInfoSource(sourceUrl, sourceDirectory.getId());
                    }
                }
            }
        } catch (Exception e) {
            logger.error(e);
        }
    }

    private void addInfoSource(String url, Long id) {
        try {
            Connection directoryConnection = Jsoup.connect(url);
            Document webSource = directoryConnection.get();
            String bodyText = webSource.outerHtml();
            Element title = webSource.select("title").first();
            String headline = title.text();
            if (!StringUtils.isEmpty(bodyText)) {
                List<String> keywords = keywordExtractor.fromHeadSection(webSource);
                InfoSource is = new InfoSource();
                is.setKeywords(keywords);
                is.setUrl(url);
                is.setContent(bodyText);
                is.setDirectoryId(id);
                is.setHeadline(headline);
                infoSourceService.create(is);
            }
        } catch (Exception e) {
            logger.error(e);
        }
    }

    @Override
    public List<String> processInfoSource(SourceDirectory srcDirectory) {
        List<String> urls = Lists.newArrayList();
        try  {
            Connection directoryConnection = Jsoup.connect(srcDirectory.getUrl());
            Document webDirectory = directoryConnection.get();
            for (Selector selector : srcDirectory.getSelectors()) {
                    Elements elements =  webDirectory.select(selector.getValue());
                for (Element element : elements) {
                    String attr = element.attr(selector.getAccessor());
                    urls.add(attr);
                }
            }
            return urls;
        } catch (Exception e) {
            logger.error(e);
            return Lists.newArrayList();
        }
    }
}
